package com.oauth.service.application;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.oauth.service.application.registry.GlobalRegistryService;
import com.oauth.service.application.registry.beans.ApplicationInfoBean;
import com.oauth.service.generic.OAuthService;
import com.oauth.service.generic.beans.OAuthServiceBean;
import com.oauth.service.generic.exception.OAuthServiceException;
import com.oauth.service.global.beans.GlobalDataType;

@Service
public class ApplicationServiceImpl implements ApplicationService {

	@Autowired
	private GlobalRegistryService<ApplicationInfoBean> globalRegistryService;

	@Autowired
	private OAuthService oauthService;

	/**
	 * @param globalRegistryService
	 *            the globalRegistryService to set
	 */
	public void setGlobalRegistryService(
			GlobalRegistryService<ApplicationInfoBean> globalRegistryService) {
		this.globalRegistryService = globalRegistryService;
	}

	/**
	 * @param oauthService
	 *            the oauthService to set
	 */
	public void setOauthService(OAuthService oauthService) {
		this.oauthService = oauthService;
	}

	@Override
	public List<ApplicationInfoBean> getSubscribedApplication(Long pMemberId)
			throws OAuthServiceException {
		Set<Long> subscribedApplicationId = getSubscribedApplicationId(pMemberId);
		return globalRegistryService.getApplicationInfo(subscribedApplicationId);
	}

	@Override
	public Set<Long> getSubscribedApplicationId(Long memberId) throws OAuthServiceException {
		return oauthService.getApplicationsByMember(memberId);
	}

	@Override
	public List<ApplicationInfoBean> getUnsubscribedApplication(Long pMemberId)
			throws OAuthServiceException {
		Set<Long> unSubscribedApplicationId = getUnsubscribedApplicationId(pMemberId);
		return globalRegistryService.getApplicationInfo(unSubscribedApplicationId);
	}

	@Override
	public Set<Long> getUnsubscribedApplicationId(Long pMemberId) throws OAuthServiceException {
		Set<Long> subscribedApplicationId = getSubscribedApplicationId(pMemberId);
		Set<Long> registerdApplicationId = globalRegistryService.getRegisterdApplicationId();
		registerdApplicationId.removeAll(subscribedApplicationId);
		return registerdApplicationId;
	}

	@Override
	public void subscribeApplication(OAuthServiceBean oauthServiceBean)
			throws OAuthServiceException {
		oauthService.persistToken(oauthServiceBean);
	}

	@Override
	public void unSubscribeApplication(Long memberId, Long applicationId)
			throws OAuthServiceException {
		oauthService.deleteToken(memberId, applicationId);

	}

	public OAuthServiceBean getToken(Long memberId, Long applicationId)
			throws OAuthServiceException {
		return oauthService.getToken(memberId, applicationId);
	}

	public List<OAuthServiceBean> getAllTokens(Long memberId) throws OAuthServiceException {
		return oauthService.getAllTokens(memberId);
	}

	@Override
	public Set<Long> getApplicationIdSetWithDataType(GlobalDataType globalDataType) {
		// NOTE: Provide cache support. Like using temporary hashmap to store
		// application with supported data types.
		Collection<ApplicationInfoBean> registerdApplication = globalRegistryService
				.getRegisterdApplication();
		Set<Long> applicationIdSet = new HashSet<Long>();
		for (ApplicationInfoBean appBean : registerdApplication) {
			if (appBean.getGlobalDataType() != null
					&& appBean.getGlobalDataType().contains(globalDataType)) {
				applicationIdSet.add(appBean.getKey());
			}
		}
		return applicationIdSet;
	}

	@Override
	public Set<Long> getApplicationIdSetWithDataTypeForMember(Long memberId,
			GlobalDataType globalDataType) throws OAuthServiceException {
		Set<Long> subscribedApplication = getSubscribedApplicationId(memberId);
		Set<Long> applicationIdSetWithDataType = getApplicationIdSetWithDataType(globalDataType);

		subscribedApplication.retainAll(applicationIdSetWithDataType);
		return subscribedApplication;
	}

	@Override
	public Collection<ApplicationInfoBean> getApplicationInfo(Set<Long> pApplicationId) {
		return globalRegistryService.getApplicationInfo(pApplicationId);
	}

	@Override
	public ApplicationInfoBean getApplicationInfo(Long applicationId) {
		return globalRegistryService.getApplicationInfo(applicationId);
	}
}
